﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace FallingRox
{
    /* The engine should be responsible for calling the Render and Collider at every iteration
    * as well as checking if any meaningful keys are pressed on the keyboard and taking appropriate decisions */
    public class Engine
    {
        IRenderer renderer;
        IUserInput userInput;
        List<Rock> allRocks;
        List<Bullet> allBullets;
        Rocket playerRocket;
        Collider collider;
        private int sleepTime;

        //constructors 
        public Engine(IRenderer renderer, Collider collider, Rocket playerRocket, IUserInput keyboardInput, int sleepTime)
        {
            this.renderer = renderer;
            this.collider = collider;
            this.userInput = keyboardInput;
            this.allRocks = new List<Rock>();
            this.allBullets = new List<Bullet>();
            this.playerRocket = playerRocket;
            this.sleepTime = sleepTime;
        }

        //methods to add object to the engine
        private Rock GenerateRock()
        {
            Random random = new Random();
            int miliseconds = DateTime.Now.Millisecond;
            return new Rock(new MatrixCoords(0, random.Next(0, FallingRoxMain.WorldCols + 1)), miliseconds % 5);
        }

        //methods to move the rocket
        public virtual void MoveRocketLeft()
        {
            this.playerRocket.MoveLeft();
        }

        public virtual void MoveRocketRight()
        {
            this.playerRocket.MoveRight();
        }

        public virtual void MoveRocketUp()
        {
            this.playerRocket.MoveUp();
        }

        public virtual void MoveRocketDown()
        {
            this.playerRocket.MoveDown();
        }

        public virtual void ShootBullet()
        {
            allBullets.Add(new Bullet(new MatrixCoords(playerRocket.Position.Row - 1, playerRocket.Position.Col + 1)));
        }

        //method to Run the engine
        public void Run()
        {
            int iteration = 0;
            while (true)
            {
                iteration++;
                List<ICollidable> collidableObjects = new List<ICollidable>();
                this.renderer.RenderAll();

                System.Threading.Thread.Sleep(this.sleepTime);
                this.renderer.ClearQueue();

                this.userInput.HandleInput();
                if (iteration % 27 == 0)
                {
                    foreach (Rock rock in allRocks)
                    {
                        rock.MoveDown();
                    }
                    allRocks.Add(this.GenerateRock());

                    foreach (Bullet bullet in allBullets)
                    {
                        bullet.MoveUp();
                    }
                }

                //Handling collisions
                foreach (var bullet in allBullets)
                {
                    this.collider.CalculateCollisions(allRocks, bullet);
                }
                this.collider.CalculateCollisions(allRocks, playerRocket);

                if (playerRocket.IsDestroyed == true)
                {
                    break;
                }

                //Deleting destroyed objects
                this.allBullets.RemoveAll(x => x.IsDestroyed);
                this.allRocks.RemoveAll(x => x.IsDestroyed);

                //Enqueueing for rendering
                this.renderer.ForRendering(playerRocket);
                foreach (var rock in allRocks)
                {
                    this.renderer.ForRendering(rock);
                }
                foreach (var bullet in allBullets)
                {
                    this.renderer.ForRendering(bullet);
                }
            }
            Console.Clear();
            Console.SetCursorPosition(30, 10);
            Console.WriteLine("Game OVER! You have been hit!");
            Console.ReadKey();
        }
    }
}
